package com.xms.configuration.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xms.configuration.entity.Settings;
import com.xms.configuration.event.SettingUpdatedEvent;
import com.xms.core.exception.XmsException;
import com.xms.event.core.IEventPublisher;
import com.xms.security.identity.ICurrentUser;
import com.xms.utils.CollectionUtil;
import com.xms.utils.JsonUtil;
import com.xms.utils.StringUtil;
import com.xms.utils.UUIDUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Field;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * SettingSaveService
 * </p>
 *
 * @author migo
 * @since 2021/10/23
 */
@Service
public class SettingSaveService implements ISettingSaveService {
    private ISettingDeleterService _settingDeleterService;
    private ISettingCreaterService _settingCreaterService;
    private IEventPublisher _eventPublisher;
    private ICurrentUser _currentUser;

    @Autowired
    public void SettingSaveService(ISettingDeleterService settingDeleterService,
                                   ISettingCreaterService settingCreaterService,
                                   IEventPublisher eventPublisher,
                                   ICurrentUser currentUser) {
        _settingDeleterService = settingDeleterService;
        _settingCreaterService = settingCreaterService;
        _eventPublisher = eventPublisher;
        _currentUser = currentUser;
    }

    @Transactional(rollbackFor=Exception.class)
    @Override
    public boolean saveMany(List<Settings> entities) throws SQLException, XmsException {
        if (CollectionUtil.isEmpty(entities)) {
            return false;
        }
        for (Settings entity : entities){
            entity.setSettingsid(UUIDUtil.get());
            entity.setCreatedon(LocalDateTime.now());
            entity.setCreatedby(_currentUser.getUser().SystemUserId);
            entity.setOrganizationid(_currentUser.getUser().OrganizationId);
        }
        List<String> names = entities.stream().map(f -> f.getName()).collect(Collectors.toList());
        _settingDeleterService.deleteMany(new LambdaQueryWrapper<Settings>().in(Settings::getName, names));
        boolean success = _settingCreaterService.createMany(entities);
        if(success){
            String name = names.get(0);
            if(name.indexOf(".") > 0) {
                name = name.substring(0, name.lastIndexOf("."));
            }
            _eventPublisher.publish(new SettingUpdatedEvent(name));
        }
        return success;
    }

    @Override
    public <T> boolean save(T setting) throws IllegalAccessException, XmsException, SQLException {
        return this.save(setting, null);
    }

    @Override
    public <T> boolean save(T setting, String nameSpace) throws IllegalAccessException, XmsException, SQLException {
        Class<?> clazz = setting.getClass();
        nameSpace = StringUtil.isEmpty(nameSpace) ? clazz.getName() : nameSpace;
        List<Settings> entities = new ArrayList<>();
        for (Field field : clazz.getFields()) {
            String key = nameSpace + "." + field.getName();
            Object value = field.get(setting);
            if (value == null) {
                continue;
            }
            if (value.getClass().equals(Object.class)) {
                value = JsonUtil.toJSONString(value);
            }
            Settings entity = new Settings();
            entity.setValue(value.toString());
            entity.setName(key);
            entities.add(entity);
        }
        return this.saveMany(entities);
    }

    @Override
    public boolean save(HashMap<String, Object> keyValues) throws XmsException, SQLException {
        if (CollectionUtil.isEmpty(keyValues)) {
            return false;
        }
        List<Settings> entities = new ArrayList<>();
        Iterator iterator = keyValues.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry entry = (Map.Entry) iterator.next();
            Object value = entry.getValue();
            if (value == null) {
                continue;
            }
            if (value.getClass().equals(Object.class)) {
                value = JsonUtil.toJSONString(value);
            }
            Settings entity = new Settings();
            entity.setValue(value.toString());
            entity.setName(entry.getKey().toString());
            entities.add(entity);
        }
        return this.saveMany(entities);
    }
}
